package com.hspedu.syn;

/**
 * @author DL5O
 * @version 1.0
 * 使用多线程，模拟三个窗口同时售票
 * 总票数 100 张
 */
public class SellTicket {
    public static void main(String[] args) {
        //第一种方式
        //测试
        /*SellTicket01 sellTicket01 = new SellTicket01();
        SellTicket01 sellTicket02 = new SellTicket01();
        SellTicket01 sellTicket03 = new SellTicket01();

        sellTicket01.start();
        sellTicket02.start();
        sellTicket03.start();*/

        /*System.out.println("===使用接口的方式来售票===");
        SellTicket02 sellTicket02 = new SellTicket02();
        Thread thread1 = new Thread(sellTicket02);
        Thread thread2 = new Thread(sellTicket02);
        Thread thread3 = new Thread(sellTicket02);
        thread1.start();//第一个线程-窗口
        thread2.start();//第二个线程-窗口
        thread3.start();//第三个线程-窗口*/

        //测试
        SellTicket03 sellTicket03 = new SellTicket03();
        Thread thread1 = new Thread(sellTicket03);
        Thread thread2 = new Thread(sellTicket03);
        Thread thread3 = new Thread(sellTicket03);
        thread1.start();//第一个线程-窗口
        thread2.start();//第二个线程-窗口
        thread3.start();//第三个线程-窗口
    }
}


//实现接口的方式,使用synchronized 实现线程同步
class SellTicket03 implements Runnable {
    private int ticketNum = 100;
    private boolean loop = true;
    Object obj =new Object();//都是同一个对象

    //同步方法(静态的) 的锁为当前类
    //1.他的锁是加载我们这个类上的 SellTicket03.Class 上
    //2.如果要在静态方法中实现一个同步代码块.
    //      synchronized (SellTicket03.class)
    public synchronized static void m1(){

    }
    public static void m2(){
        synchronized (SellTicket03.class){
            System.out.println("m2");
        }
    }

    //是在方法上加的锁
    //说明
    //1.public synchronized void sell()就是一个同步方法
    //2.这时锁是在this对象
    //3.也可以在代码块上写 synchronized,同步代码块,互斥锁还是在this对象
    public /*synchronized*/ void sell() {//同步方法，在同一个时刻只能有一个线程来执行我们的run方法
        synchronized (/*this*/obj){
            if (ticketNum <= 0) {
                loop = false;
                System.out.println("票已售空，售票结束..");
                return;
            }

            //休眠50毫秒
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName()
                    + " 售出一张票," + "剩余票数=" + (--ticketNum));
        }
    }


    @Override
    public void run() {

        while (loop) {
            sell();
        }
    }
}


//使用第一种继承thread的方式
//new SellTicket01().start()
//new SellTicket01().start() this只对当前的对象有效
class SellTicket01 extends Thread {
    private static int ticketNum = 100;//让多个线程共享 ticketNum

    //锁一般用于共享的只有
    public void m1(){
        synchronized (this){
            System.out.println("hello");
        }
    }

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("售票结束..");
                break;
            }
            //休眠50毫秒
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName()
                    + " 售出一张票" + "剩余票数=" + (--ticketNum));
        }
    }
}

//实现接口的方式
class SellTicket02 implements Runnable {
    private int ticketNum = 100;

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("售票结束..");
                break;
            }
            //休眠50毫秒
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName()
                    + " 售出一张票" + "剩余票数=" + (--ticketNum));
        }
    }
}
